package com.angus.modules.content.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.angus.api.front.factory.RemoteFrontUserFallbackFactory;
import com.angus.common.core.enums.ContentType;
import com.angus.common.core.exception.ServiceException;
import com.angus.common.core.utils.uuid.IdUtils;
import com.angus.common.security.utils.SecurityUtils;
import com.angus.modules.content.domain.*;
import com.angus.modules.content.dto.AddCourseDto;
import com.angus.modules.content.mapper.CourseLockMapper;
import com.angus.modules.content.repository.*;
import com.angus.modules.content.service.ICourseService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import javax.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author liyanan
 * @date 2024/10/21 10:00 AM
 * @description
 */
@Service
public class CourseServiceImpl implements ICourseService {

    private static final Logger log = LoggerFactory.getLogger(
        RemoteFrontUserFallbackFactory.class
    );

    @Resource
    private CourseLockMapper courseLockMapper;

    @Resource
    private CourseRepository courseRepository;

    @Resource
    private CNContentRepository cnContentRepository;

    @Resource
    private ENContentRepository enContentRepository;

    @Resource
    private CNQuestionRepository cnQuestionRepository;

    @Resource
    private ENQuestionRepository enQuestionRepository;

    @Resource
    private CNOptionRepository cnOptionRepository;

    @Resource
    private ENOptionRepository enOptionRepository;

    @Resource
    private SysUnitRepository unitRepository;

    @Resource
    private SysUnitRepository sysUnitRepository;

    @Override
    public List<Course> getCourseList() {
        return courseRepository.list(
            new QueryWrapper<Course>().orderByDesc("sort")
        );
    }

    @Override
    public List<Course> getUpCourseList(String type) {
        return courseRepository.list(
            Wrappers.lambdaQuery(Course.class)
                .eq(Course::getStatus, 1)
                .eq(Course::getContentType, type)
        );
    }

    @Override
    public Course addCourse(AddCourseDto dto) {
        Course courseData = courseRepository.getCourseByName(
            dto.getCourseName()
        );
        if (Objects.nonNull(courseData)) {
            throw new ServiceException("课程已存在");
        }

        Course course = new Course();
        course.setContentType(dto.getContentType());
        course.setCourseName(dto.getCourseName());
        course.setCourseAmount(dto.getCourseAmount());
        course.setCommissionRate(dto.getCommissionRate());
        course.setStatus(dto.getStatus());
        course.setCreateBy(SecurityUtils.getUsername());
        course.setCreateTime(LocalDateTime.now());
        course.setUpdateBy(SecurityUtils.getUsername());
        course.setUpdateTime(LocalDateTime.now());
        course.setCourseCode(IdUtils.generateAlphanumericStr(6));
        courseRepository.save(course);
        return course;
    }

    @Override
    public Course getById(Long id) {
        return courseRepository.getById(id);
    }

    @Override
    public List<Long> getByIds(List<Long> ids) {
        return courseRepository.listByIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(List<Long> ids) {
        return courseRepository.deleteByIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clearCourse(String courseCode, String type) {
        sysUnitRepository
            .getBaseMapper()
            .delete(
                Wrappers.lambdaQuery(SysUnit.class).eq(
                    SysUnit::getCourseCode,
                    courseCode
                )
            );
        if (ContentType.CN.getTypeCode().equals(type)) {
            cnContentRepository
                .getBaseMapper()
                .delete(
                    Wrappers.lambdaQuery(CNContent.class).eq(
                        CNContent::getCourseCode,
                        courseCode
                    )
                );
            cnQuestionRepository
                .getBaseMapper()
                .delete(
                    Wrappers.lambdaQuery(CNCourseQuestion.class).eq(
                        CNCourseQuestion::getCourseCode,
                        courseCode
                    )
                );
        } else if (ContentType.EN.getTypeCode().equals(type)) {
            enContentRepository
                .getBaseMapper()
                .delete(
                    Wrappers.lambdaQuery(ENContent.class).eq(
                        ENContent::getCourseCode,
                        courseCode
                    )
                );
            enQuestionRepository
                .getBaseMapper()
                .delete(
                    Wrappers.lambdaQuery(ENCourseQuestion.class).eq(
                        ENCourseQuestion::getCourseCode,
                        courseCode
                    )
                );
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clearQuestion(String courseCode, String type) {
        if (ContentType.CN.getTypeCode().equals(type)) {
            cnQuestionRepository
                .getBaseMapper()
                .delete(
                    Wrappers.lambdaQuery(CNCourseQuestion.class).eq(
                        CNCourseQuestion::getCourseCode,
                        courseCode
                    )
                );
            cnOptionRepository.
                getBaseMapper().
                delete(
                    Wrappers.lambdaQuery(CNOption.class).eq(
                        CNOption::getCourseCode,
                        courseCode
                    )
                );
        } else if (ContentType.EN.getTypeCode().equals(type)) {
            enQuestionRepository
                .getBaseMapper()
                .delete(
                    Wrappers.lambdaQuery(ENCourseQuestion.class).eq(
                        ENCourseQuestion::getCourseCode,
                        courseCode
                    )
                );
            enOptionRepository.
                getBaseMapper().
                delete(
                    Wrappers.lambdaQuery(ENOption.class).eq(
                        ENOption::getCourseCode,
                        courseCode
                    )
                );
        }
    }

    @Override
    public boolean modifyCourse(Course course) {
        course.setUpdateBy(SecurityUtils.getUsername());
        course.setUpdateTime(LocalDateTime.now());
        return courseRepository.updateById(course);
    }

    @Override
    public List<Course> getCourseByType(String type) {
        return courseRepository.getCourseByType(type);
    }

    @Override
    public boolean updateStatus(Long id, Integer value) {
        return courseRepository.updateStatus(id, value);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateCNPExe(String courseCode) {
        List<CNContent> cnContentList = cnContentRepository.getByCourseCode(
            courseCode
        );
        List<CNCourseQuestion> questionResult = generatePQuestion(
            cnContentList,
            courseCode
        );
        List<CNOption> cnOptions = generatePOption(
            cnContentList,
            questionResult
        );
        cnOptionRepository.saveBatch(cnOptions);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateCNWExe(String courseCode) {
        List<CNContent> cnContentList = cnContentRepository.getByCourseCode(
            courseCode
        );
        List<CNCourseQuestion> questionResult = generateWQuestion(
            cnContentList,
            courseCode
        );
        List<CNOption> cnOptions = generateWOption(
            cnContentList,
            questionResult
        );
        cnOptionRepository.saveBatch(cnOptions);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void GenCNCourseSentenceStr(String courseCode) {
        List<CNContent> cnContentList = cnContentRepository.getByCourseCode(
            courseCode
        );
        List<CNCourseQuestion> questionResult = generateSentenceQuestion(
            cnContentList,
            courseCode
        );
        List<CNOption> cnOptions = generateSentenceOption(
            cnContentList,
            questionResult
        );
        cnOptionRepository.saveBatch(cnOptions);
    }

    private List<CNOption> generateWOption(
        List<CNContent> cnContentList,
        List<CNCourseQuestion> questionResult
    ) {
        // 内容分组
        Map<Long, List<CNContent>> contentListMap = cnContentList
            .stream()
            .filter(content -> !content.getGroupFlag().contains("s"))
            .collect(Collectors.groupingBy(CNContent::getGroupId));

        // 生成选项
        return questionResult
            .stream()
            .flatMap(question -> {
                List<CNContent> cnContents = contentListMap.get(
                    question.getGroupId()
                );
                // 生成正确选项
                List<CNOption> correctOptions = cnContents
                    .stream()
                    .filter(content ->
                        content.getGroupFlag().equals(question.getGroupFlag())
                    )
                    .map(cnContent ->
                        createOption(question.getId(), cnContent.getCnWord(), 1, cnContent.getCnPinyin(), cnContent.getCourseCode())
                    )
                    .collect(Collectors.toList());
                // 生成错误选项
                List<CNContent> otherContents = cnContents
                    .stream()
                    .filter(content ->
                        !question.getGroupFlag().equals(content.getGroupFlag())
                    )
                    .collect(Collectors.toList());

                Random random = new Random();
                int numWrongOptions = 3; // 假设每个问题有3个错误选项
                List<CNOption> wrongOptions = IntStream.range(
                    0,
                    numWrongOptions
                )
                    .mapToObj(i -> {
                        CNContent wrongContent = getRandomElement(
                            otherContents,
                            random
                        );
                        if (wrongContent != null) {
                            return createOption(
                                question.getId(),
                                wrongContent.getCnWord(),
                                0, wrongContent.getCnPinyin(), wrongContent.getCourseCode()
                            );
                        }
                        return null;
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

                // 合并正确和错误选项
                return Stream.concat(
                    correctOptions.stream(),
                    wrongOptions.stream()
                );
            })
            .collect(Collectors.toList());
    }

    @SuppressWarnings("null")
    private List<CNCourseQuestion> generateWQuestion(
        List<CNContent> cnContentList,
        String courseCode
    ) {
        String regex = "&nbsp;";
        Map<Long, List<CNContent>> contentListMap = cnContentList
            .stream()
            .filter(content -> !content.getGroupFlag().contains("s"))
            .collect(Collectors.groupingBy(CNContent::getGroupId));
        List<CNCourseQuestion> questionList = new ArrayList<>();
        for (Long groupId : contentListMap.keySet()) {
            List<SysUnit> sysUnits = unitRepository.selectAllUnits(
                courseCode,
                groupId
            );
            SysUnit sysUnit = null;
            if (CollUtil.isNotEmpty(sysUnits)) {
                sysUnit = sysUnits.get(0);
            }
            List<CNContent> cnContents = contentListMap.get(groupId);
            for (CNContent cnContent : cnContents) {
                String s = "";
                if (cnContent.getCnParaphrase().contains(regex)) {
                    String[] splits = cnContent.getCnParaphrase().split(regex);
                    s = Arrays.asList(splits).get(1);
                } else {
                    s = cnContent.getCnParaphrase();
                }
                CNCourseQuestion question = new CNCourseQuestion();
                question.setCourseCode(courseCode);
                question.setUnitNum(sysUnit.getUnitNum());
                question.setQuestionTitle(s);
                question.setGroupFlag(cnContent.getGroupFlag());
                question.setGroupId(cnContent.getGroupId());
                question.setQuestionType(2);
                question.setOptionType(0);
                question.setCreateTime(LocalDateTime.now());
                Boolean isExist = cnQuestionRepository.getQuestion(
                    question.getCourseCode(),
                    question.getGroupId(),
                    question.getGroupFlag(),
                    question.getQuestionType()
                );
                if (Boolean.FALSE.equals(isExist)) {
                    questionList.add(question);
                }
            }
        }
        cnQuestionRepository.saveBatch(questionList);
        return questionList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateENPExe(String courseCode) {
        List<ENContent> enContentList = enContentRepository.getByCourseCode(
            courseCode
        );
        List<ENCourseQuestion> questionResult = generateENPQuestion(
            enContentList,
            courseCode
        );
        List<ENOption> enOptions = generateENPOption(
            enContentList,
            questionResult
        );
        enOptionRepository.saveBatch(enOptions);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void generateENWExe(String courseCode) {
        List<ENContent> contentList = enContentRepository.getByCourseCode(
            courseCode
        );
        List<ENCourseQuestion> questionResult = generateENWQuestion(
            contentList,
            courseCode
        );
        List<ENOption> options = generateENWOption(contentList, questionResult);
        enOptionRepository.saveBatch(options);
    }

    @SuppressWarnings("null")
    private List<ENCourseQuestion> generateENWQuestion(
        List<ENContent> cnContentList,
        String courseCode
    ) {
        Map<Long, List<ENContent>> contentListMap = cnContentList
            .stream()
            .filter(content -> !content.getGroupFlag().contains("s"))
            .collect(Collectors.groupingBy(ENContent::getGroupId));
        List<ENCourseQuestion> questionList = new ArrayList<>();
        for (Long groupId : contentListMap.keySet()) {
            List<SysUnit> sysUnits = unitRepository.selectAllUnits(
                courseCode,
                groupId
            );
            SysUnit sysUnit = null;
            if (CollUtil.isNotEmpty(sysUnits)) {
                sysUnit = sysUnits.get(0);
            }
            List<ENContent> contents = contentListMap.get(groupId);
            for (ENContent content : contents) {
                ENCourseQuestion question = new ENCourseQuestion();
                question.setCourseCode(courseCode);
                question.setUnitNum(sysUnit.getUnitNum());
                question.setQuestionTitle(content.getEnTranslation());
                question.setGroupFlag(content.getGroupFlag());
                question.setGroupId(content.getGroupId());
                question.setQuestionType(2);
                question.setOptionType(0);
                question.setCreateTime(LocalDateTime.now());
                Boolean isExist = cnQuestionRepository.getQuestion(
                    question.getCourseCode(),
                    question.getGroupId(),
                    question.getGroupFlag(),
                    question.getQuestionType()
                );
                if (Boolean.FALSE.equals(isExist)) {
                    questionList.add(question);
                }
            }
        }
        enQuestionRepository.saveBatch(questionList);
        return questionList;
    }

    private List<ENOption> generateENWOption(
        List<ENContent> cnContentList,
        List<ENCourseQuestion> questionResult
    ) {
        // 内容分组
        Map<Long, List<ENContent>> contentListMap = cnContentList
            .stream()
            .filter(content -> !content.getGroupFlag().contains("s"))
            .collect(Collectors.groupingBy(ENContent::getGroupId));

        // 生成选项
        return questionResult
            .stream()
            .flatMap(question -> {
                List<ENContent> cnContents = contentListMap.get(
                    question.getGroupId()
                );
                // 生成正确选项
                List<ENOption> correctOptions = cnContents
                    .stream()
                    .filter(content ->
                        content.getGroupFlag().equals(question.getGroupFlag())
                    )
                    .map(enContent ->
                        createENOption(
                            question.getId(),
                            enContent.getEnWord(),
                            1,
                                enContent.getCourseCode()
                        )
                    )
                    .collect(Collectors.toList());

                // 生成错误选项
                List<ENContent> otherContents = cnContents
                    .stream()
                    .filter(groupId -> !question.getGroupId().equals(groupId))
                    .collect(Collectors.toList());

                Random random = new Random();
                int numWrongOptions = 3; // 假设每个问题有3个错误选项
                List<ENOption> wrongOptions = IntStream.range(
                    0,
                    numWrongOptions
                )
                    .mapToObj(i -> {
                        ENContent wrongContent = getRandomElement(
                            otherContents,
                            random
                        );
                        if (wrongContent != null) {
                            return createENOption(
                                question.getId(),
                                wrongContent.getEnWord(),
                                0,
                                    wrongContent.getCourseCode()
                            );
                        }
                        return null;
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());

                // 合并正确和错误选项
                return Stream.concat(
                    correctOptions.stream(),
                    wrongOptions.stream()
                );
            })
            .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void GenENCourseSentenceStr(String courseCode) {
        List<ENContent> enContentList = enContentRepository.getByCourseCode(
            courseCode
        );
        List<ENCourseQuestion> questionResult = generateENSentenceQuestion(
            enContentList,
            courseCode
        );
        List<ENOption> enOptions = generateENSentenceOption(
            enContentList,
            questionResult
        );
        enOptionRepository.saveBatch(enOptions);
    }

    private List<ENOption> generateENSentenceOption(
        List<ENContent> enContentList,
        List<ENCourseQuestion> questionResult
    ) {
        Map<Long, List<ENContent>> contentListMap = enContentList
            .stream()
            .collect(Collectors.groupingBy(ENContent::getGroupId));
        return questionResult
            .stream()
            .flatMap(question -> {
                List<ENContent> enContents = contentListMap.get(
                    question.getGroupId()
                );
                List<ENOption> rightList = enContents
                    .stream()
                    .filter(enContent -> enContent.getGroupFlag().contains("s"))
                    .map(enContent ->
                        createENOption(
                            question.getId(),
                            enContent.getEnWord(),
                            1,
                                enContent.getCourseCode()
                        )
                    )
                    .collect(Collectors.toList());
                return rightList.stream();
            })
            .collect(Collectors.toList());
    }

    @SuppressWarnings("null")
    private List<ENCourseQuestion> generateENSentenceQuestion(
        List<ENContent> enContentList,
        String courseCode
    ) {
        List<ENCourseQuestion> questionList = new ArrayList<>();
        Map<Long, List<ENContent>> contentListMap = enContentList
            .stream()
            .filter(c -> c.getGroupFlag().contains("s"))
            .collect(Collectors.groupingBy(ENContent::getGroupId));
        for (Long groupId : contentListMap.keySet()) {
            List<SysUnit> sysUnits = unitRepository.selectAllUnits(
                courseCode,
                groupId
            );
            SysUnit sysUnit = null;
            if (CollUtil.isNotEmpty(sysUnits)) {
                sysUnit = sysUnits.get(0);
            }
            List<ENContent> cnContents = contentListMap.get(groupId);
            for (ENContent content : cnContents) {
                ENCourseQuestion question = new ENCourseQuestion();
                question.setUnitNum(sysUnit.getUnitNum());
                question.setCourseCode(courseCode);
                question.setQuestionTitle(content.getEnWord());
                question.setGroupFlag(content.getGroupFlag());
                question.setField1(content.getEnTranslation());
                question.setGroupId(content.getGroupId());
                question.setQuestionType(0);
                question.setOptionType(2);
                question.setCreateTime(LocalDateTime.now());
                Boolean isExist = enQuestionRepository.getQuestion(
                    question.getCourseCode(),
                    question.getGroupId(),
                    question.getGroupFlag(),
                    question.getQuestionType()
                );
                if (Boolean.FALSE.equals(isExist)) {
                    questionList.add(question);
                }
            }
        }
        enQuestionRepository.saveBatch(questionList);
        return questionList;
    }

    private List<CNOption> generateSentenceOption(
        List<CNContent> cnContentList,
        List<CNCourseQuestion> questionResult
    ) {
        Map<Long, List<CNContent>> contentListMap = cnContentList
            .stream()
            .collect(Collectors.groupingBy(CNContent::getGroupId));
        return questionResult
            .stream()
            .flatMap(question -> {
                List<CNContent> cnContents = contentListMap.get(
                    question.getGroupId()
                );
                List<CNOption> rightList = cnContents
                    .stream()
                    .filter(cnContent -> cnContent.getGroupFlag().contains("s"))
                    .map(cnContent ->
                        createOption(question.getId(), cnContent.getCnWord(), 1,cnContent.getCnPinyin(), cnContent.getCourseCode())
                    )
                    .collect(Collectors.toList());
                return rightList.stream();
            })
            .collect(Collectors.toList());
    }

    @SuppressWarnings("null")
    private List<CNCourseQuestion> generateSentenceQuestion(
        List<CNContent> cnContentList,
        String courseCode
    ) {
        List<CNCourseQuestion> questionList = new ArrayList<>();
        Map<Long, List<CNContent>> contentListMap = cnContentList
            .stream()
            .filter(c -> c.getGroupFlag().contains("s"))
            .collect(Collectors.groupingBy(CNContent::getGroupId));
        for (Long groupId : contentListMap.keySet()) {
            List<SysUnit> sysUnits = unitRepository.selectAllUnits(
                courseCode,
                groupId
            );
            SysUnit sysUnit = null;
            if (CollUtil.isNotEmpty(sysUnits)) {
                sysUnit = sysUnits.get(0);
            }
            List<CNContent> cnContents = contentListMap.get(groupId);
            for (CNContent content : cnContents) {
                CNCourseQuestion question = new CNCourseQuestion();
                question.setUnitNum(sysUnit.getUnitNum());
                question.setCourseCode(courseCode);
                question.setQuestionTitle(content.getCnWord());
                question.setGroupFlag(content.getGroupFlag());
                question.setGroupId(content.getGroupId());
                question.setField1(content.getCnTranslation());
                question.setQuestionType(0);
                question.setOptionType(2);
                question.setCreateTime(LocalDateTime.now());
                Boolean isExist = cnQuestionRepository.getQuestion(
                    question.getCourseCode(),
                    question.getGroupId(),
                    question.getGroupFlag(),
                    question.getQuestionType()
                );
                if (Boolean.FALSE.equals(isExist)) {
                    questionList.add(question);
                }
            }
        }
        cnQuestionRepository.saveBatch(questionList);
        return questionList;
    }

    @SuppressWarnings("null")
    private List<CNCourseQuestion> generatePQuestion(
        List<CNContent> contents,
        String courseCode
    ) {
        List<CNCourseQuestion> questionList = new ArrayList<>();
        Map<Long, List<CNContent>> contentListMap = contents
            .stream()
            .filter(content -> !content.getGroupFlag().contains("s"))
            .collect(Collectors.groupingBy(CNContent::getGroupId));
        for (Long groupId : contentListMap.keySet()) {
            List<SysUnit> sysUnits = unitRepository.selectAllUnits(
                courseCode,
                groupId
            );
            SysUnit sysUnit = null;
            if (CollUtil.isNotEmpty(sysUnits)) {
                sysUnit = sysUnits.get(0);
            }
            List<CNContent> cnContents = contentListMap.get(groupId);
            for (CNContent content : cnContents) {
                CNCourseQuestion question = new CNCourseQuestion();
                question.setUnitNum(sysUnit.getUnitNum());
                question.setCourseCode(courseCode);
                question.setQuestionTitle(content.getCnWord());
                question.setGroupFlag(content.getGroupFlag());
                question.setGroupId(content.getGroupId());
                question.setField1(content.getCnPinyin());
                question.setQuestionType(1);
                question.setOptionType(0);
                question.setCreateTime(LocalDateTime.now());
                question.setReadAloud(content.getReadAloud());
                question.setMp3Content(content.getMp3Content());
                Boolean isExist = cnQuestionRepository.getQuestion(
                    question.getCourseCode(),
                    question.getGroupId(),
                    question.getGroupFlag(),
                    question.getQuestionType()
                );
                if (Boolean.FALSE.equals(isExist)) {
                    questionList.add(question);
                }
            }
        }
        cnQuestionRepository.saveBatch(questionList);
        return questionList;
    }

    @SuppressWarnings("null")
    private List<ENCourseQuestion> generateENPQuestion(
        List<ENContent> contents,
        String courseCode
    ) {
        List<ENCourseQuestion> questionList = new ArrayList<>();
        Map<Long, List<ENContent>> contentListMap = contents
            .stream()
            .filter(content -> !content.getGroupFlag().contains("s"))
            .collect(Collectors.groupingBy(ENContent::getGroupId));
        for (Long groupId : contentListMap.keySet()) {
            List<SysUnit> sysUnits = unitRepository.selectAllUnits(
                courseCode,
                groupId
            );
            SysUnit sysUnit = null;
            if (CollUtil.isNotEmpty(sysUnits)) {
                sysUnit = sysUnits.get(0);
            }
            List<ENContent> enContents = contentListMap.get(groupId);
            for (ENContent content : enContents) {
                ENCourseQuestion question = new ENCourseQuestion();
                question.setUnitNum(sysUnit.getUnitNum());
                question.setCourseCode(courseCode);
                question.setQuestionTitle(content.getEnWord());
                question.setGroupFlag(content.getGroupFlag());
                question.setGroupId(content.getGroupId());
                // question.setField1(content.getEnSymbol());
                question.setField1(content.getEnWord());
                question.setQuestionType(1);
                question.setOptionType(0);
                question.setCreateTime(LocalDateTime.now());
                question.setReadAloud(content.getReadAloud());
                Boolean isExist = enQuestionRepository.getQuestion(
                    question.getCourseCode(),
                    question.getGroupId(),
                    question.getGroupFlag(),
                    question.getQuestionType()
                );
                if (Boolean.FALSE.equals(isExist)) {
                    questionList.add(question);
                }
            }
        }
        enQuestionRepository.saveBatch(questionList);
        return questionList;
    }

    private List<CNOption> generatePOption(
        List<CNContent> cnContentList,
        List<CNCourseQuestion> questionResult
    ) {
        String regex = "&nbsp;";

        Map<Long, List<CNContent>> contentListMap = cnContentList
            .stream()
            .filter(content -> !content.getGroupFlag().contains("s"))
            .collect(Collectors.groupingBy(CNContent::getGroupId));

        return questionResult
            .stream()
            .flatMap(question -> {
                List<CNContent> groupContentList = contentListMap.get(
                    question.getGroupId()
                );
                // 正确选项的内容
                CNContent rightContent = groupContentList
                    .stream()
                    .filter(content ->
                        content.getGroupFlag().equals(question.getGroupFlag())
                    )
                    .findFirst()
                    .orElse(null);
                // 生成正确选项 ddl
                String[] cnParaphrase = rightContent.getCnParaphrase().split(regex);
                Set<CNOption> rightSet = Arrays.stream(cnParaphrase)
                    .filter(s -> s.length() > 0)
                    .collect(
                        Collectors.collectingAndThen(
                            Collectors.toList(),
                            list -> {
                                Collections.shuffle(list);
                                return list.stream();
                            }
                        )
                    )
                    .limit(1)
                    .map(s -> createOption(question.getId(), s, 1,"", question.getCourseCode()))
                    .collect(Collectors.toSet());

                // 错误选项的原始数据
                List<CNContent> errorContentList = groupContentList
                    .stream()
                    .filter(content ->
                        !content.getGroupFlag().equals(question.getGroupFlag())
                    )
                    .collect(Collectors.toList());
                // 生成错误选项 ddl
                Set<CNOption> errorSet = errorContentList
                    .stream()
                    .flatMap(content -> {
                        String[] contentParaphrase = content.getCnParaphrase().split(regex);
                        return Arrays.stream(contentParaphrase);
                    })
                    .filter(s -> s.length() > 0)
                    .distinct() // 去重
                    .collect(
                        Collectors.collectingAndThen(
                            Collectors.toList(),
                            list -> {
                                Collections.shuffle(list);
                                return list.stream();
                            }
                        )
                    )
                    .limit(3)
                    .map(s -> createOption(question.getId(), s, 0,"", question.getCourseCode()))
                    .collect(Collectors.toSet());

                // 合并正确和错误选项
                return Stream.concat(rightSet.stream(), errorSet.stream());
            })
            .collect(Collectors.toList());
    }

    private List<ENOption> generateENPOption(
        List<ENContent> enContentList,
        List<ENCourseQuestion> questionResult
    ) {
        Map<Long, List<ENContent>> contentListMap = enContentList
            .stream()
            .filter(content -> !content.getGroupFlag().contains("s"))
            .collect(Collectors.groupingBy(ENContent::getGroupId));

        return questionResult
            .stream()
            .flatMap(question -> {
                List<ENContent> groupContentList = contentListMap.get(
                    question.getGroupId()
                );
                // 正确选项的内容
                ENContent rightContent = groupContentList
                    .stream()
                    .filter(content ->
                        content.getGroupFlag().equals(question.getGroupFlag())
                    )
                    .findFirst()
                    .orElse(null);
                // 生成正确选项 ddl
                Set<ENOption> rightSet = Collections.singletonList(rightContent)
                    .stream()
                    .map(s ->
                        createENOption(
                            question.getId(),
                            s.getEnTranslation(),
                            1,
                                s.getCourseCode()
                        )
                    )
                    .collect(Collectors.toSet());

                // 错误选项的原始数据
                List<ENContent> errorContentList = groupContentList
                    .stream()
                    .filter(content ->
                        !content.getGroupFlag().equals(question.getGroupFlag())
                    )
                    .collect(Collectors.toList());

                // 生成错误选项 ddl
                Random random = new Random();
                int numWrongOptions = 3; // 假设每个问题有3个错误选项
                Set<ENOption> errorSet = IntStream.range(0, numWrongOptions)
                    .mapToObj(i -> {
                        ENContent wrongContent = getRandomElement(
                            errorContentList,
                            random
                        );
                        if (wrongContent != null) {
                            return createENOption(
                                question.getId(),
                                wrongContent.getEnTranslation(),
                                0, question.getCourseCode()
                            );
                        }
                        return null;
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toSet());

                // 合并正确和错误选项
                return Stream.concat(rightSet.stream(), errorSet.stream());
            })
            .collect(Collectors.toList());
    }

    private CNOption createOption(
        Long questionId,
        String optionValue,
        int rightOption,
        String field1,
        String courseCode
    ) {
        CNOption option = new CNOption();
        option.setQuestionId(questionId);
        option.setOptionValue(optionValue);
        option.setRightOption(rightOption);
        option.setField1(field1);
        option.setCreateTime(LocalDateTime.now());
        option.setCourseCode(courseCode);
        return option;
    }

    private ENOption createENOption(
        Long questionId,
        String optionValue,
        int rightOption,
        String courseCode
    ) {
        ENOption option = new ENOption();
        option.setQuestionId(questionId);
        option.setOptionValue(optionValue);
        option.setRightOption(rightOption);
        option.setCreateTime(LocalDateTime.now());
        option.setCourseCode(courseCode);
        return option;
    }

    private <T> T getRandomElement(Collection<T> collection, Random random) {
        List<T> list = new ArrayList<>(collection);
        return list.isEmpty() ? null : list.get(random.nextInt(list.size()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void GenCourseExercises(String courseCode, String type) {
        Lock lock = courseLockMapper.getLock(courseCode);
        lock.lock();
        try {
            if (ContentType.CN.getTypeCode().equals(type)) {
                if (!isDataExists(courseCode, 0, type)) {
                    // 中文词汇 - 造句       questionType = 0
                    GenCNCourseSentenceStr(courseCode);
                }
                if (!isDataExists(courseCode, 1, type)) {
                    // 中文词汇 - 看字选释义  questionType = 1
                    generateCNPExe(courseCode);
                }
                if (!isDataExists(courseCode, 2, type)) {
                    // 中文词汇 - 看释义选字  questionType = 2
                    generateCNWExe(courseCode);
                }
                log.info("中文课程：{} 生成成功", courseCode);
            }
            if (ContentType.EN.getTypeCode().equals(type)) {
                if (!isDataExists(courseCode, 0, type)) {
                    // 英文词汇 - 造句       questionType = 0
                    GenENCourseSentenceStr(courseCode);
                }
                if (!isDataExists(courseCode, 1, type)) {
                    // 英文词汇 - 看字选释义  questionType = 1
                    generateENPExe(courseCode);
                }
                if (!isDataExists(courseCode, 2, type)) {
                    // 英文词汇 - 看释义选字  questionType = 2
                    generateENWExe(courseCode);
                }
                log.info("英语课程：{} 生成成功", courseCode);
            }
        } catch (Exception e) {
            log.error(
                "英语课程：{} 生成失败, 错误: {}",
                courseCode,
                e.getMessage()
            );
        } finally {
            lock.unlock();
        }
    }

    // 检查数据是否存在（幂等性校验）
    private boolean isDataExists(
        String courseCode,
        Integer questionType,
        String type
    ) {
        // 示例：从数据库或配置中读取
        if (ContentType.CN.getTypeCode().equals(type)) {
            return cnQuestionRepository.getQuestionByCourse(
                courseCode,
                questionType
            );
        }
        if (ContentType.EN.getTypeCode().equals(type)) {
            return enQuestionRepository.getQuestionByCourse(
                courseCode,
                questionType
            );
        }
        return false;
    }
}
